/**
 * YUICompressorFilterReader
 * @author fabio at maas
 * ant 1.9.0
 * yuicompressor-2.4.2
 */
package it.ccr.maas.tools.ant;
 
import jargs.gnu.CmdLineParser;
import jargs.gnu.CmdLineParser.IllegalOptionValueException;
import jargs.gnu.CmdLineParser.UnknownOptionException;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;

import org.apache.tools.ant.filters.BaseParamFilterReader;
import org.apache.tools.ant.types.Parameter;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;

import com.yahoo.platform.yui.compressor.CssCompressor;
import com.yahoo.platform.yui.compressor.JavaScriptCompressor;

public class YUICompressorFilterReader extends BaseParamFilterReader {
  public YUICompressorFilterReader(Reader in){
    super(in);
    try {initialize();} 
    catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }
  int pos = 0;
  StringBuffer result;
  public int read() throws IOException {
   if (pos>=result.length()) return -1;
   return result.charAt(pos++);
  }
  private void initialize() throws IllegalOptionValueException, UnknownOptionException, IOException{
    ArrayList<String>listArgs = new ArrayList<String>();
    Parameter params[] = getParameters();
    for(int j=0; params!=null && j<params.length; j++){
      listArgs.add(params[j].getName());
      listArgs.add(params[j].getValue());
    }
    String[]args = new String[listArgs.size()];
    args = listArgs.toArray(args);
    // see com.yahoo.platform.yui.compressor.YUICompressor
    CmdLineParser parser = new CmdLineParser();
    CmdLineParser.Option typeOpt = parser.addStringOption("type");
    CmdLineParser.Option verboseOpt = parser.addBooleanOption('v', "verbose");
    CmdLineParser.Option nomungeOpt = parser.addBooleanOption("nomunge");
    CmdLineParser.Option linebreakOpt = parser.addStringOption("line-break");
    CmdLineParser.Option preserveSemiOpt = parser.addBooleanOption("preserve-semi");
    CmdLineParser.Option disableOptimizationsOpt = parser.addBooleanOption("disable-optimizations");
    CmdLineParser.Option charsetOpt = parser.addStringOption("charset");
    parser.parse(args);
    boolean verbose = parser.getOptionValue(verboseOpt) != null;
    String charset = (String) parser.getOptionValue(charsetOpt);
    if (charset == null || !Charset.isSupported(charset)) {
      charset = System.getProperty("file.encoding");
      if (charset == null) charset = "UTF-8";
    }
    String linebreakstr = (String) parser.getOptionValue(linebreakOpt);
    int linebreakpos = -1;
    if (linebreakstr != null) linebreakpos = Integer.parseInt(linebreakstr, 10);
    StringWriter out = new StringWriter();
    String type = (String) parser.getOptionValue(typeOpt);
    if (type==null||type.length()==0) type="js";
    if (type.equalsIgnoreCase("js")) {
      boolean munge = parser.getOptionValue(nomungeOpt) == null;
      boolean preserveAllSemiColons = parser.getOptionValue(preserveSemiOpt) != null;
      boolean disableOptimizations = parser.getOptionValue(disableOptimizationsOpt) != null;
      JavaScriptCompressor compressor = new JavaScriptCompressor(in, new ErrorReporter() {
        public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
          if (line < 0) System.err.println("\n[WARNING] " + message);
          else System.err.println("\n[WARNING] " + line + ':' + lineOffset + ':' + message);
        }
        public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
          if (line < 0) System.err.println("\n[ERROR] " + message);
          else System.err.println("\n[ERROR] " + line + ':' + lineOffset + ':' + message);
        }
        public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) {
          error(message, sourceName, line, lineSource, lineOffset);
          return new EvaluatorException(message);
        }
      });
      compressor.compress(out, linebreakpos, munge, verbose, preserveAllSemiColons, disableOptimizations);
    }
    else if (type.equalsIgnoreCase("css")) {
     CssCompressor compressor = new CssCompressor(in);
     in.close();
     compressor.compress(out, linebreakpos);
    }
    else throw new IOException("unrecognized type " + type);
    result = out.getBuffer();
  }  
}
